package org.example.Frame;

import org.example.Pojo.*;
import org.example.Util.FileUtil;
import org.example.implement.MyFrame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;

public class Game extends JFrame implements  KeyListener,MyFrame,Runnable {

    private User player;//当前使用的用户
    private Vector<User> playscore;//成绩数组-->计算排名
    private int difficulty;//可以获取到难度信息

    private File img;//选择的图片

    private Gamepojo gameobject;//拼图

    private GameButton gameButton;//游戏界面的所有按钮

    private GameScore gameScore;//游戏成绩
    private int length;//二维数组长度
    private boolean win;//判断游戏的输赢
    private int frequency;//悔棋次数
    private int lastStep;//上一步的e.getKeyCode()
    private int ScoreSum;//总分
    //初始化
    public Game(int difficulty, File img,int time,User player) throws HeadlessException {
        //界面初始化
        this.addKeyListener(this);
        this.setFocusable(true);//设置为可聚焦
        this.requestFocusInWindow();
        this.setTitle("游戏界面");
        this.setSize(1400,800);//根据难度调整大小，然后切片也跟着移动
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //变量初始化
        this.difficulty = difficulty;
        this.img = img;
        if(difficulty==0) length=3;
        else length=difficulty+4;
        String[] fileingex=img.getName().split("\\.");
        this.gameobject=new Gamepojo(length,fileingex[0]);
        this.gameButton=new GameButton();
        this.gameScore=new GameScore(time);
        this.win=false;//游戏输赢
        this.frequency=0;
        this.lastStep=0;
        //玩家信息初始化
        this.player=player;
        try {
            playscore=FileUtil.ReadScore();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //需要对数组进行排序
        Collections.sort(playscore);
        //绘画板
        JPanel panel=new JPanel();
        draw(panel);
        this.add(panel);
        this.setVisible(true);
        //开启游戏进行的线程
        new Thread(gameobject).start();
        //System.out.println("线程继续");//测试代码
        //限时判断初始化
        if(time!=0)
            new Thread(this).start();
        //测试文件类
//        try {
//            FileUtil.ReadplayScore(player);
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }
    }

    //绘画板（非常重要!!!!!!）
    @Override
    public void draw(JPanel panel){
        panel.setLayout(null);
        //panel.setBackground(Color.DARK_GRAY);
        //将图片放好
        gameobject.getCompleteImg().setBounds(30,250,300,300);//完整图片放置;
        panel.add(gameobject.getCompleteImg());
        //切片放置
        for(int i=0;i<length;i++){
            for(int j=0;j<length;j++){
                gameobject.getSectionImg()[i][j].setBounds(j*(720/length)+360,i*(720/length)+10,(720/length),(720/length));
                panel.add(gameobject.getSectionImg()[i][j]);
            }
        }
        //按钮放置
        for(int i=0;i<gameButton.getButtons().length;i++){
            JButton button=gameButton.getButtons()[i];
            button.setBounds(1180,80+ i*120,120,40);
            panel.add(button);
        }
        //提前结束游戏按钮设置
        gameButton.getEnd().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(gameobject.getmove())
                        close();
                    requestFocusInWindow();
                }
            });
        //重新开始设置
        gameButton.getAgain().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    //System.out.println("aa");
                    if(gameobject.getmove()) {
                        gameobject.setMove(false);
                        gameScore.setFact(0);
                        gameScore.getStep().setText(Integer.toString(gameScore.getFact()));
                        new Thread(gameobject).start();
                        requestFocusInWindow();
                    }
                }
            });

        //悔棋
        gameButton.getRegret().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(gameobject.getmove()){
                        if(frequency==0&&gameScore.getFact()!=0) {
                            gameScore.setFact(gameScore.getFact()-1);
                            frequency++;
                            gameScore.getStep().setText(Integer.toString(gameScore.getFact()));
                            //返回逻辑
                            //保存上一步laststep
                            //然后写方法进行回退
                            regert();
                        }
                        else{
                            JOptionPane.showMessageDialog(new JOptionPane(),"悔棋失败","警告",JOptionPane.WARNING_MESSAGE);
                        }
                        requestFocusInWindow();
                    }
                }
            });

        //刷新界面
        gameButton.getBack().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(gameobject.getmove()){
                        gameobject.back=true;
                        gameobject.setMove(false);
                        new Thread(gameobject).start();
                    }
                    requestFocusInWindow();
                }
            });

        //帮助界面
        gameButton.getHelp().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(gameobject.getmove()){
                    new Help();//显示帮助界面
                    requestFocusInWindow();
                }
            }
        });
        //时间位置
        JLabel timeLabel=new JLabel("时间:");
        timeLabel.setFont(new Font("宋体", Font.PLAIN, 24));
        timeLabel.setBounds(10,0,80,80);
        panel.add(timeLabel);
        //时间标签
        gameScore.getTimelabel().setFont(new Font("宋体", Font.PLAIN, 24));
        gameScore.getTimelabel().setBounds(100,0,200,80);
        panel.add(gameScore.getTimelabel());
        gameScore.getTimer().start();
        //步数标签
        JLabel steplable=new JLabel("步数:");
        steplable.setFont(new Font("宋体", Font.PLAIN, 24));
        steplable.setBounds(10,100,80,80);
        panel.add(steplable);
        gameScore.getStep().setBounds(100,100,80,80);
        panel.add(gameScore.getStep());
    }
    @Override
    public void close() {
        this.setVisible(false);
        if(win){
            SumScore();//计算总分
            //获取该玩家这次的成绩排名
            int rank=getrank();
            System.out.println("排名为"+rank);
            //对成绩进行记录并且写到文件中
            player.setScore(ScoreSum);
            player.setLocalTime(gameScore.getLocalTime());//获取的时间字符串为"00:00:00"格式
            try {
                FileUtil.WriteScore(player);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            new Score(rank,player);//这里要传入玩家信息
        }
    }
    //获取排名
    private int getrank() {
        for(int i=1;i<=playscore.size();i++){
            if(playscore.get(i-1)!=null&&ScoreSum>=playscore.get(i-1).getScore())return i;
        }
        return playscore.size()+1;
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }
    @Override
    public void keyPressed(KeyEvent e) {
        //System.out.println("1");
        if(gameobject.getmove()){
            Blank blank=gameobject.getBlank();
            int row=blank.getRow();
            int col=blank.getCol();
            //System.out.println(row+" "+col);//测试代码
            lastStep=e.getKeyCode();//获取这次移动的数字
            //System.out.println(e.getKeyCode());
            if(e.getKeyCode()==KeyEvent.VK_W&&row+1!=length){
                movesection(row,col,row+1,col);
            }
            else if(e.getKeyCode()==KeyEvent.VK_S&&row-1!=-1){
                movesection(row,col,row-1,col);
            }
            else if(e.getKeyCode()==KeyEvent.VK_D&&col-1!=-1){
                movesection(row,col,row,col-1);
            }
            else if(e.getKeyCode()==KeyEvent.VK_A&&col+1!=length){
                movesection(row,col,row,col+1);
            }
            text();
            win=jubgewin();//只有胜利才会位true
            if(win)close();//如果获取胜利，启动成绩记录
        }//可移动的时候-->move==true才能进行移动
    }

    @Override
    public void keyReleased(KeyEvent e) {}

    //移动切片方法
    public void movesection(int row1,int col1,int row2,int col2){
        MySection section1=null;
        MySection section2=null;
        CountDownLatch latch=new CountDownLatch(2);
        //移动结束后对图片二维数组和map进行交换，然后对blank进行更新
        section1=new MySection(row2,col2,col1,row1, gameobject.getSectionImg(), latch);
        section2=new MySection(row1,col1,col2,row2, gameobject.getSectionImg(), latch);
        section1.setJudge(1);
        section2.setJudge(1);
        new Thread(section1).start();
        new Thread(section2).start();
        try {
            latch.await();
        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }
        //System.out.println("移动结束");
        exchange(row1,col1,row2,col2);
        blankupdate(row2,col2);
        gameScore.setFact(gameScore.getFact()+1);
        gameScore.getStep().setText(Integer.toString(gameScore.getFact()));
    }

    //移动后交换
    public void exchange(int row1,int col1,int row2,int col2) {
        //交换图片数组
        JLabel jLabel=gameobject.getSectionImg()[row1][col1];
        gameobject.getSectionImg()[row1][col1]=gameobject.getSectionImg()[row2][col2];
        gameobject.getSectionImg()[row2][col2]=jLabel;
        //System.out.println(gameobject.getSectionImg()[row1][col1]+" "+gameobject.getSectionImg()[row2][col2]);
        //交换map
        int tem=gameobject.getMap()[row1][col1];
        gameobject.getMap()[row1][col1]=gameobject.getMap()[row2][col2];
        gameobject.getMap()[row2][col2]=tem;
        //System.out.println(gameobject.getMap()[row1][col1]+" "+gameobject.getMap()[row2][col2]);
    }

    //更新空白位置
    public void blankupdate(int row, int col) {
        gameobject.getBlank().setCol(col);
        gameobject.getBlank().setRow(row);
        //System.out.println("row+col="+row+" "+col);
    }

    //判断是否胜利
    public boolean jubgewin() {
        for(int i=0;i<length;i++){
            for(int j=0;j<length;j++){
                if((j!=length-1&&gameobject.getMap()[i][j]+1!=gameobject.getMap()[i][j+1])||(i!=length-1&&j==length-1&&gameobject.getMap()[i+1][0]!=gameobject.getMap()[i][j]+1))
                    return false;
            }
        }
        return true;
    }

    //测试方法检测map数组
    private void text() {
        System.out.println("当前map数组为");
        for(int i=0;i<length;i++){
            for(int j=0;j<length;j++){
                System.out.print(gameobject.getMap()[i][j]+" ");
            }
            System.out.println();
        }
    }

    //悔棋方法
    public void regert(){
        Blank blank=gameobject.getBlank();
        int row=blank.getRow();
        int col=blank.getCol();
        if(lastStep==KeyEvent.VK_W){
            movesection(row,col,row-1,col);
        }
        else if(lastStep==KeyEvent.VK_S){
            movesection(row,col,row+1,col);
        }
        else if(lastStep==KeyEvent.VK_D){
            movesection(row,col,row,col+1);
        }
        else if(lastStep==KeyEvent.VK_A){
            movesection(row,col,row,col-1);
        }

    }
    //每时每刻判断是否到达时间
    @Override
    public void run() {
        while(!gameScore.arrival){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }//死循环卡住代码等待到达限时
            close();//win为false,没有成绩
    }
    //计算总分
    public void SumScore(){
        int moveScore= (gameobject.getTheory()/gameScore.getFact())*100;//理论步数
        //int moveScore=10;//测试变量
        int timeScore= gameScore.getTimeScore();
        ScoreSum=moveScore+timeScore;
    }
}

